package com.wlyuan.open.domain.source.dispatcher.conversion;

import com.wlyuan.core.exception.AssertUtils;
import com.wlyuan.core.exception.ValueError;
import com.wlyuan.open.domain.source.dispatcher.consignee.CreateConsignee;
import com.wlyuan.open.domain.source.dispatcher.customer.CreateCustomer;
import com.wlyuan.open.dto.OpenOrderSyncDTO;
import com.wlyuan.open.remote.facade.AddressDTO;
import com.wlyuan.open.remote.facade.CustomerFacade;
import com.wlyuan.open.remote.facade.GoodsFacade;
import com.wlyuan.open.remote.facade.constants.Constants;
import com.wlyuan.open.utils.LongUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Optional;

/**
 * @author lijing
 * @description
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class OpenDispatcherOrderConversion implements OpenDispatcherConversion<OpenOrderSyncDTO> {
    private final BaseOpenDispatcherConversion baseOpenDispatcherConversion;
    private final GoodsFacade goodsFacade;
    private final CustomerFacade customerFacade;

    @Override
    public void convert(OpenOrderSyncDTO source) {
        //租户id转换
        tenantConvert(source);
        //转换客户ID 制单人id 签收人id 回单人id 关单人id
        infoConvert(source);
        // 收货人ID
        consigneeConvert(source);
        // 物品ID
        goodsConvert(source);
        //地区
        convertArea(source);
    }

    private void tenantConvert(OpenOrderSyncDTO source) {
        var tenant = source.getTenantId();
        if (LongUtils.notNullLong(tenant)) {
            var tenantId = baseOpenDispatcherConversion.tenant(tenant);
            AssertUtils.assertNotNull(tenantId, new ValueError("OpenOrderSyncDTO租户不存在:" + tenant), source);
            source.setTenantId(tenantId);
            Optional.ofNullable(source.getOrderReceiptDevice()).ifPresent(orderReceiptDevice -> orderReceiptDevice.setTenantId(tenantId));
        }
    }

    private void infoConvert(OpenOrderSyncDTO source) {
        var orderInfo = source.getInfo();
        Optional.ofNullable(orderInfo).ifPresent(info -> {
            //客户租户
            var customerTenant = info.getCustomerTenantId();
            if (LongUtils.notNullLong(customerTenant)) {
                var tenantId = baseOpenDispatcherConversion.tenant(customerTenant);
                AssertUtils.assertNotNull(tenantId, new ValueError("OpenOrderSyncDTO客户租户不存在:" + customerTenant), source);
                info.setCustomerTenantId(tenantId);
            }
            //制单人
            if (LongUtils.notNullLong(info.getCreateMan())) {
                var createId = baseOpenDispatcherConversion.user(info.getCreateMan());
                AssertUtils.assertNotNull(createId, new ValueError("OpenOrderSyncDTO制单人不存在:" + info.getCreateMan()), source);
                info.setCreateMan(createId);
            }

            //签收人
            if (LongUtils.notNullLong(info.getSignBy())) {
                var signId = baseOpenDispatcherConversion.user(info.getSignBy());
                AssertUtils.assertNotNull(signId, new ValueError("OpenOrderSyncDTO签单人不存在:" + info.getSignBy()), source);
                info.setSignBy(signId);
            }

            //回单人
            if (LongUtils.notNullLong(info.getReceiptBy())) {
                var receiptId = baseOpenDispatcherConversion.user(info.getReceiptBy());
                AssertUtils.assertNotNull(receiptId, new ValueError("OpenOrderSyncDTO回单人不存在:" + info.getReceiptBy()), source);
                info.setReceiptBy(receiptId);
            }

            //关单人
            if (LongUtils.notNullLong(info.getCloseBy())) {
                var closeId = baseOpenDispatcherConversion.user(info.getCloseBy());
                AssertUtils.assertNotNull(closeId, new ValueError("OpenOrderSyncDTO关单人不存在:" + info.getCloseBy()), source);
                info.setCloseBy(closeId);
            }

            //客户
            if (LongUtils.notNullLong(info.getCustomerId())) {
                var customer = baseOpenDispatcherConversion.customer(info.getCustomerId(), info.getCustomerType(), info.getCustomerTenantId());
                AssertUtils.assertNotNull(customer, new ValueError("OpenOrderSyncDTO客户不存在:" + info.getCustomerId()), source);
                info.setCustomerId(customer.getCustomerId());
                if (StringUtils.isNotBlank(customer.getCustomerName())) {
                    info.setCustomerName(customer.getCustomerName());
                }
            } else {
                //为空或者0 , 创建线下客户
                var customer = customerFacade.createCustomer(new CreateCustomer(info.getCustomerName(), source.getFrom().getContactMobile(), source.getFrom().getContactName(), info.getCustomerTenantId(), source.getInfo().getCreateMan()));
                info.setCustomerId(customer.getCustomerId());
                info.setCustomerName(customer.getName());
            }
        });
    }

    private void consigneeConvert(OpenOrderSyncDTO source) {
        var to = source.getTo();
        Optional.ofNullable(to).ifPresent(endUser -> {
            //创建收货方
            var create = new CreateConsignee(endUser.getConsigneeName(), endUser.getContactMobile(), endUser.getContactName(),
                    source.getInfo().getCustomerId(), source.getInfo().getCustomerName(), source.getTenantId(), source.getInfo().getCreateMan());
            var consignee = baseOpenDispatcherConversion.consignee(create);
            endUser.setConsigneeId(consignee.getConsigneeId());
            source.getInfo().setConsigneeId(consignee.getConsigneeId());
        });
    }

    private void goodsConvert(OpenOrderSyncDTO source) {
        if (CollectionUtils.isEmpty(source.getGoodsList())) {
            return;
        }
        source.getGoodsList().forEach(orderGoodsDTO -> {
            //创建物品
            var goods = goodsFacade.createGoods(orderGoodsDTO, source.getInfo().getCustomerId(), source.getTenantId(), source.getInfo().getCreateMan());
            orderGoodsDTO.setGoodsId(goods.getGoodsId());
        });

        baseOpenDispatcherConversion.generateBatchNo(source.getGoodsList());

    }

    private void convertArea(OpenOrderSyncDTO source) {
        Optional.ofNullable(source.getFrom()).ifPresent(f -> {
            if (StringUtils.isNotBlank(f.getProvince()) || StringUtils.isNotBlank(f.getCity()) || StringUtils.isNotBlank(f.getDistrict()) || StringUtils.isNotBlank(f.getAddress())) {
                var area = baseOpenDispatcherConversion.area(new AddressDTO(f.getProvinceCode(), f.getProvince(), f.getCityCode(), f.getCity(), f.getDistrictCode(), f.getDistrict(), f.getAddress(), Constants.LEVEL));
                AssertUtils.assertNotNull(area, new ValueError("OpenOrderSyncDTO 发货地址不存在:" + f.getProvince() + "," + f.getCity() + "," + f.getDistrict() + "," + f.getAddress()), source);
                f.setProvinceCode(area.getProvinceCode());
                f.setProvince(area.getProvinceName());
                f.setCityCode(area.getCityCode());
                f.setCity(area.getCityName());
                f.setDistrictCode(area.getDistrictCode());
                f.setDistrict(area.getDistrictName());
                if (StringUtils.isBlank(f.getLocation()) && StringUtils.isNotBlank(area.getLat()) && StringUtils.isNotBlank(area.getLon())) {
                    f.setLocation(area.getLat() + "," + area.getLon());
                }
                if (StringUtils.isBlank(f.getAddress())) {
                    f.setAddress("#");
                }
            }
        });

        Optional.ofNullable(source.getTo()).ifPresent(t -> {
            if (StringUtils.isNotBlank(t.getProvince()) || StringUtils.isNotBlank(t.getCity()) || StringUtils.isNotBlank(t.getDistrict()) || StringUtils.isNotBlank(t.getAddress())) {
                var area = baseOpenDispatcherConversion.area(new AddressDTO(t.getProvinceCode(), t.getProvince(), t.getCityCode(), t.getCity(), t.getDistrictCode(), t.getDistrict(), t.getAddress(), Constants.LEVEL));
                AssertUtils.assertNotNull(area, new ValueError("OpenOrderSyncDTO 收货地址不存在:" + t.getProvince() + "," + t.getCity() + "," + t.getDistrict() + "," + t.getAddress()), source);
                t.setProvinceCode(area.getProvinceCode());
                t.setProvince(area.getProvinceName());
                t.setCityCode(area.getCityCode());
                t.setCity(area.getCityName());
                t.setDistrictCode(area.getDistrictCode());
                t.setDistrict(area.getDistrictName());
                if (StringUtils.isBlank(t.getLocation()) && StringUtils.isNotBlank(area.getLat()) && StringUtils.isNotBlank(area.getLon())) {
                    t.setLocation(area.getLat() + "," + area.getLon());
                }
                if (StringUtils.isBlank(t.getAddress())) {
                    t.setAddress("#");
                }
            }
        });

        if (!CollectionUtils.isEmpty(source.getTransports())) {
            source.getTransports().forEach(data -> {
                if (StringUtils.isNotBlank(data.getWayProvince()) || StringUtils.isNotBlank(data.getWayCity()) || StringUtils.isNotBlank(data.getWayDistrict()) || StringUtils.isNotBlank(data.getWayTo())) {
                    var area = baseOpenDispatcherConversion.area(new AddressDTO(data.getWayProvinceCode() != null ? String.valueOf(data.getWayProvinceCode()) : null, data.getWayProvince(),
                            data.getWayCityCode() != null ? String.valueOf(data.getWayCityCode()) : null, data.getWayCity(),
                            data.getWayDistrictCode() != null ? String.valueOf(data.getWayDistrictCode()) : null, data.getWayDistrict(), data.getWayTo(), Constants.LEVEL));
                    AssertUtils.assertNotNull(area, new ValueError("OpenOrderSyncDTO 多段轨迹 地区不存在:" + data.getWayProvince() + "," + data.getWayCity() + "," + data.getWayDistrict() + "," + data.getWayTo()), source);
                    data.setWayProvinceCode(StringUtils.isNotBlank(area.getProvinceCode()) ? Long.valueOf(area.getProvinceCode()) : null);
                    data.setWayProvince(area.getProvinceName());
                    data.setWayCityCode(StringUtils.isNotBlank(area.getCityCode()) ? Long.valueOf(area.getCityCode()) : null);
                    data.setWayCity(area.getCityName());
                    data.setWayDistrictCode(StringUtils.isNotBlank(area.getDistrictCode()) ? Long.valueOf(area.getDistrictCode()) : null);
                    data.setWayDistrict(area.getDistrictName());
                    if (StringUtils.isBlank(data.getWayTo())) {
                        data.setWayTo("#");
                    }
                }
            });
        }
    }
}
